package cn.yang37.utils;

import cn.yang37.cons.MagicConstant;
import cn.yang37.cons.PemTypeEnums;
import org.bouncycastle.util.io.pem.PemObject;
import org.bouncycastle.util.io.pem.PemWriter;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringWriter;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.util.Base64;

/**
 * @description:
 * @class: DerAndPemUtils
 * @author: yang37z@qq.com
 * @date: 2025/3/26 1:54
 * @version: 1.0
 */
public class DerAndPemUtils {

    /**
     * DER转PEM（通用类型）
     *
     * @param derData DER字节数组
     * @param pemType PEM头标识类型
     */
    public static String der2Pem(byte[] derData, PemTypeEnums pemType) throws IOException {
        try (StringWriter sw = new StringWriter(); PemWriter pw = new PemWriter(sw)) {
            pw.writeObject(new PemObject(pemType.getType(), derData));
            pw.flush();
            return sw.toString();
        }
    }

    /**
     * PEM转DER（通用类型）
     *
     * @param pemData PEM字符串
     */
    public static byte[] pem2Der(String pemData) {
        String normalized = pemData.trim()
                .replaceAll("-+BEGIN.+?-+", "")
                .replaceAll("-+END.+?-+", "")
                .replaceAll("\\s", "");
        return Base64.getDecoder().decode(normalized);
    }

    /**
     * X509证书DER转PEM（带类型校验）
     */
    public static String x509Der2Pem(byte[] derCert) throws CertificateException, IOException {
        // 验证证书有效性
        CertificateFactory cf = CertificateFactory.getInstance("X.509");
        cf.generateCertificate(new ByteArrayInputStream(derCert));

        return der2Pem(derCert, PemTypeEnums.CERTIFICATE);
    }

    /**
     * X509证书PEM转DER（带类型校验）
     *
     * @param pemCert PEM字符串（必须包含-----BEGIN CERTIFICATE-----标识）
     */
    public static byte[] x509Pem2Der(String pemCert) throws CertificateException {
        // 1. 类型校验（检查PEM头标识）
        if (!pemCert.contains(MagicConstant.CERTIFICATE_BEGIN)) {
            throw new CertificateException("Invalid PEM format: missing certificate header");
        }

        // 2. 调用通用PEM转DER方法
        byte[] derData = pem2Der(pemCert);

        // 3. 验证DER有效性
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X.509");
            cf.generateCertificate(new ByteArrayInputStream(derData));
        } catch (CertificateException e) {
            throw new CertificateException("Invalid X.509 certificate after conversion", e);
        }

        return derData;
    }
}